﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Opc.Ua;
using Opc.Ua.Client;


namespace Siemens.OpcUA.SimpleClient
{
    public partial class MainForm : Form
    {



        public MainForm()
        {
            InitializeComponent();

        }



        public Server m_Server = null;

        public bool m_Connected = false;

        private Subscription m_Subscription;

       



        private void MainForm_Load(object sender, EventArgs e)
        {

            // Create client API server object
            m_Server = new Server();
            // Attach to certificate event
            m_Server.CertificateEvent += new certificateValidation(m_Server_CertificateEvent);

            gBRW.Enabled = false;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }

        void m_Server_CertificateEvent(CertificateValidator validator, CertificateValidationEventArgs e)
        {
            // Accept all certificate -> better ask user
            e.Accept = true;
        }

        private void BtnConnect_Click(object sender, EventArgs e)
        {
            try
            {

                if (m_Connected)
                {
                    Disconnect();
                }

                else
                {

                    Connect();
                    

                }
            }
            catch (Exception)
            {

                if (m_Connected)
                {
                    TSLable.Text = "操作提示：断开失败";
                }
                else
                {
                    TSLable.Text = "操作提示：连接失败";
                }

            }
        }

        private int Connect()
        {

            if (txtServerUrl.Text.Length == 0)
            {
                return -1;
            }

            // Set wait cursor.
            Cursor = Cursors.WaitCursor;
            int result = 0;

            try
            {
                EndpointWrapper wrapper;
                string endpointUrl;



                // The URL has been entered as text.
                endpointUrl = txtServerUrl.Text;



                // Call connect with URL
                m_Server.Connect(endpointUrl);


                // Connect succeeded.
                m_Connected = true;



                // State is connected now.
                btnConnect.Text = "断开";

                // Update status label.
                TSLable.Text = "连接服务器成功，连接点： " + endpointUrl;


                txtServerUrl.Enabled = false;
                gBRW.Enabled = true;
            }
            catch (Exception e)
            {
                if (m_Connected)
                {
                    // Disconnect from server.
                    Disconnect();
                }

                result = -1;
                m_Connected = false;

                // Update status label.
                TSLable.Text = "连接服务器失败，信息： " + e.Message;

            }

            // Set default cursor.
            Cursor = Cursors.Default;
            return result;
        }

        /// <summary>
        /// Disconnect from server.
        /// </summary>
        private int Disconnect()
        {
            int result;

            try
            {
                // Call the disconnect service of the server.
                result = m_Server.Disconnect();

                // Disconnect succeeded.
                if (result == 0)
                {

                    // Set flag.
                    m_Connected = false;

                    // Update status label.
                    TSLable.Text = "与服务器断开连接成功";


                    // State is connected now.
                    btnConnect.Text = "连接";

                    // Enable the combobox to respond to user interaction.
                    txtServerUrl.Enabled = true;
                    gBRW.Enabled = false;
                }
                // Disconnect failed. 
                else
                {
                    // Error case.
                    m_Connected = true;

                    // Update status label.
                    TSLable.Text = "连接服务器失败，信息：" + result.ToString();

                }
            }
            catch (Exception e)
            {
                result = -1;

                // Update status label.
                TSLable.Text = "与服务器断开连接时出现异常，信息：" + e.Message;

            }


            return result;
        }




        private void BtnRead_Click(object sender, EventArgs e)
        {


            try
            {
                DataValueCollection m_currentValues;
                // Prepare call to ClientAPI.
                NodeIdCollection nodesToRead = new NodeIdCollection();


                // NodeIds.

                nodesToRead.Add(new NodeId(textBoxNodeId1.Text.Trim()));
                nodesToRead.Add(new NodeId(textBoxNodeId2.Text.Trim()));


                // Call to ClientAPI.
                m_Server.ReadValues(
                    nodesToRead,
                    out m_currentValues);




                textBoxNodeId1Value.Text = m_currentValues[0].Value.ToString();
                textBoxNodeId2Value.Text = m_currentValues[1].Value.ToString();


                // Update status label.
                TSLable.Text = "读取值成功";

            }
            catch (Exception ex)
            {
                // Update status label.
                TSLable.Text = "读取值时出现异常，信息： "
                     + ex.Message;
            }
        }

        private void BtnWrite_Click(object sender, EventArgs e)
        {
            try
            {


                DataValueCollection m_currentValues;
                // Prepare call to ClientAPI.
                NodeIdCollection nodesToWrite = new NodeIdCollection();
                DataValueCollection values = new DataValueCollection();
                StatusCodeCollection results = null;



                // NodeIds.

                nodesToWrite.Add(new NodeId(textBoxNodeId1.Text.Trim()));
                nodesToWrite.Add(new NodeId(textBoxNodeId2.Text.Trim()));

                // Call to ClientAPI.
                m_Server.ReadValues(
                    nodesToWrite,
                    out m_currentValues);


                // Values to write.


                values.Add(new DataValue(new Variant(Convert.ChangeType(textBoxNodeId1CValue.Text.Trim(), m_currentValues[0].Value.GetType()))));
                values.Add(new DataValue(new Variant(Convert.ChangeType(textBoxNodeId2CValue.Text.Trim(), m_currentValues[1].Value.GetType()))));



                // Call to ClientAPI.
                m_Server.WriteValues(
                    nodesToWrite,
                    values,
                    out results);

                //// Call to ClientAPI.
                //m_Server.ReadValues(
                //    nodesToWrite,
                //    out m_currentValues);

                //textBoxNodeId1Value.Text = m_currentValues[0].Value.ToString();
                //textBoxNodeId2Value.Text = m_currentValues[1].Value.ToString();


                // Update status label.
                TSLable.Text = "写入值成功";
            }
            catch (Exception ex)
            {
                // Update status label.
                TSLable.Text = "写入值时出现异常，信息： "
                    + ex.Message;
            }
        }
        //---------------------------------------------------------------------------------------



       
        List<ListViewItem> NodeitemsList = new List<ListViewItem>();
        private void BtnSok_Click(object sender, EventArgs e)
        {

            ListViewItem tempItem = null;
            SubjectItemsAdd(textBoxNodeId1.Text.Trim(),ref tempItem);

            NodeitemsList.Add(tempItem);

            SubjectItemsAdd(textBoxNodeId2.Text.Trim(), ref tempItem);

            NodeitemsList.Add(tempItem);

        }

        private void SubjectItemsAdd(string NodeId,ref ListViewItem NodeItem)
        {
            try
            {

                // Retrieve the event data and create the according nodeid. 
                string sNodeId = NodeId;
                NodeId nodeId = new NodeId(sNodeId);


                // Create the subscription if it does not already exist.
                if (m_Subscription == null)
                {
                    m_Subscription = m_Server.AddSubscription(100);
                }

                // Add the attribute name/value to the list view.
                ListViewItem item = new ListViewItem(sNodeId);
                object serverHandle = null;

                // Prepare further columns.
                item.SubItems.Add("100"); // Sampling interval by default.
                item.SubItems.Add(String.Empty);
                item.SubItems.Add(String.Empty);
                item.SubItems.Add(String.Empty);
                item.SubItems.Add(String.Empty);
                item.SubItems.Add(String.Empty);


                try
                {
                    // Add the item and apply any changes to it. 
                    m_Subscription.AddDataMonitoredItem(nodeId, item, ClientApi_ValueChanged, 100, out serverHandle);


                    // Update status label.
                    TSLable.Text = "节点添加订阅成功， " +
                     nodeId.ToString();

                }
                catch (ServiceResultException monitoredItemResult)
                {
                    item.SubItems[5].Text = monitoredItemResult.StatusCode.ToString();

                    // Update status label.
                    TSLable.Text = "添加订阅时出现异常，信息： " +
                      monitoredItemResult.Message;
                }

                item.Tag = serverHandle;


                NodeItem = item; 

            }
            catch (Exception exception)
            {                         
                // Update status label.
               TSLable.Text = "添加订阅时出现异常，信息： " +
                        exception.Message;
            }
        }

        private void BtnSno_Click(object sender, EventArgs e)
        {
          
            foreach (var item in NodeitemsList)
            {
                SubjectItemsDel(item);
            }
          

        }
        private void SubjectItemsDel(ListViewItem NodeItem)
        {
            try
            {
                // check if operation is currently allowed.
                if (m_Subscription.Session == null || m_Subscription.innerSubscription == null )
                {
                    return;
                }

    
                        m_Subscription.RemoveMonitoredItem(NodeItem.Tag);




                // Update status label.
                TSLable.Text="节点从订阅列表移除成功";
            }
            catch (Exception exception)
            {
                // Update status label.
                TSLable.Text = "节点从订阅列表移除时出现异常，信息：" +
                    exception.Message;
            }
        }
     
        /// <summary>
        /// Callback to receive data changes from an UA server.
        /// </summary>
        /// <param name="clientHandle">The source of the event.</param>
        /// <param name="value">The instance containing the changed data.</param>
        private void ClientApi_ValueChanged(object clientHandle, DataValue value)
        {
            // We have to call an invoke method. 
            if (this.InvokeRequired)
            {
                // Asynchronous execution of the valueChanged delegate.
                this.BeginInvoke(new valueChanged(ClientApi_ValueChanged), clientHandle, value);
                return;
            }

            // Get the according item.
            ListViewItem item = (ListViewItem)clientHandle;

            // Set current value, status code and timestamp.
            item.SubItems[2].Text = Utils.Format("{0}", value.Value);
            item.SubItems[3].Text = Utils.Format("{0}", value.StatusCode);
            item.SubItems[4].Text = Utils.Format("{0:HH:mm:ss.fff}", value.SourceTimestamp.ToLocalTime());

            
           
            CheckSubItem(clientHandle,item);
        }

        private void CheckSubItem(object clientHandle,ListViewItem item)
        {
           
            string[] sArray = clientHandle.ToString().Split(new char[2] { '{', '}' });
            if (sArray.Length > 2)
            {
                if (sArray[1] == textBoxNodeId1.Text.Trim()) textBoxNodeId1Value.Text = item.SubItems[2].Text;

                if (sArray[1] == textBoxNodeId2.Text.Trim()) textBoxNodeId2Value.Text = item.SubItems[2].Text;

            }
        }
    }
}
